/**
 * 
 */
package idv.takeshi.software.productline.bookstore.presentation.web.controller;

import idv.takeshi.software.productline.bookstore.application.service.BrowseBooksService;
import idv.takeshi.software.productline.bookstore.application.service.Constants;
import idv.takeshi.software.productline.bookstore.domain.model.book.Book;
import idv.takeshi.software.productline.bookstore.domain.model.category.Category;
import idv.takeshi.software.productline.bookstore.domain.model.shoppingcart.ShoppingCart;

import java.util.Set;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * A Controller for book store browsing operations.
 * @author takeshi
 *
 */
@Controller("browseBooksController")
public class BrowseBooksController {
	
	@Autowired
	private BrowseBooksService browseBookService;
	
	private int numberOfBooksPerSummaryPage;
	private int numberOfBooksPerDetailPage;
	
	@RequestMapping(value = "/main.html", method = RequestMethod.GET)
	public void browseCategoriesAndBooksSummary(
			@RequestParam(required = false) Long selectedCategoryId, 
			@RequestParam(required = false) Long sidebarCategoryId,
			ModelMap modelMap, HttpSession session){
		Category rootCategory = null;
		Category selectedCategory = null;
		Category sidebarCategory = null;
		Long determinedSelectedCategoryId = null;
		Long determinedSidebarCategoryId = null;
		ShoppingCart shoppingCart = null;
		
		if(null != sidebarCategoryId){
			determinedSidebarCategoryId = sidebarCategoryId;
		} else{
			sidebarCategory = (Category) session.getAttribute(Constants.SIDEBAR_CATEGORY_NAME);
			determinedSidebarCategoryId = sidebarCategory.getId();
		}
		
		rootCategory = (Category) session.getAttribute(Constants.ROOT_CATEGORY_NAME);
		
		shoppingCart = (ShoppingCart) session.getAttribute(Constants.SHOPPING_CART_NAME);
		
		determinedSelectedCategoryId = null == selectedCategoryId? determinedSidebarCategoryId: selectedCategoryId;
		
		sidebarCategory = rootCategory.getAllSubCategory(determinedSidebarCategoryId);
		selectedCategory = rootCategory.getAllSubCategory(determinedSelectedCategoryId);
		Set<Category> selectedParentCategories = rootCategory.getSuperCategories(selectedCategory);
		//add itself
		selectedParentCategories.add(selectedCategory);
		
		modelMap.put("selectedCategoryId", determinedSelectedCategoryId);
		modelMap.put("selectedCategory", selectedCategory);
		session.setAttribute(Constants.ROOT_CATEGORY_NAME, rootCategory);
		modelMap.put("sidebarCategoryId", determinedSidebarCategoryId);
		session.setAttribute(Constants.SIDEBAR_CATEGORY_NAME, sidebarCategory);
		modelMap.put("bestSellers", selectedCategory.getAllBestSellers(numberOfBooksPerSummaryPage));
		modelMap.put("newestBooks", selectedCategory.getAllNewestBooks(this.numberOfBooksPerSummaryPage));
		modelMap.put("selectedParentCategories", selectedParentCategories);
		session.setAttribute(Constants.SHOPPING_CART_NAME, shoppingCart);
	}
	
	@RequestMapping(value = "/details.html", method = RequestMethod.GET)
	public void browseCategoriesAndBooksDetail(
			@RequestParam Long selectedCategoryId,
			@RequestParam boolean isBestSellers, //otherwise, isNewestBooks
			@RequestParam int pageNo,
			ModelMap modelMap, HttpSession session){
		
		Category rootCategory = (Category)session.getAttribute(Constants.ROOT_CATEGORY_NAME);
		Category category = rootCategory.getAllSubCategory(selectedCategoryId);
		Set<Category> selectedParentCategories = rootCategory.getSuperCategories(category);
		
		//add itself
		selectedParentCategories.add(category);
		
		Set<Book> books = null;
		int maxBooks = 0;
		
		books = this.browseBookService.getBooksByPageNoAndBookAmountPerPage(
				isBestSellers, pageNo, numberOfBooksPerDetailPage, category);
		if(isBestSellers){
			maxBooks = category.getAllBestSellers().size();
		} else{
			maxBooks = category.getAllNewestBooks().size();
		}
		
		modelMap.put("selectedCategoryId", selectedCategoryId);
		modelMap.put("isBestSellers", isBestSellers);
		modelMap.put("selectedParentCategories", selectedParentCategories);
		modelMap.put("books", books);
		modelMap.put("maxBooks", maxBooks);
		modelMap.put("numberOfBooksPerDetailPage", numberOfBooksPerDetailPage);
		modelMap.put("pageNo", pageNo);
	}
	
	@RequestMapping(value = "/book/details.html", method = RequestMethod.GET)
	public void browseABookDetail(
			@RequestParam Long bookId,
			ModelMap modelMap, HttpSession session){
		Category superCategory = (Category) session.getAttribute(Constants.ROOT_CATEGORY_NAME);
		
		Book book = this.browseBookService.getBookById(bookId);
		Long selectedCategoryId = superCategory.getSuperCategory(book).getId();
		Set<Category> selectedParentCategories = superCategory.getSuperCategories(book);
		
		modelMap.put("selectedCategoryId", selectedCategoryId);
		modelMap.put("selectedParentCategories", selectedParentCategories);
		modelMap.put("book", book);
	}
	
	@RequestMapping(value = "/search.html")
	public void searchBookDetails(
			@RequestParam String keyWord, 
			@RequestParam int pageNo,
			ModelMap modelMap){
		Set<Book> books = null;
		books = this.browseBookService.getBooksByPageNoAndBookAmountPerPage(
				keyWord, pageNo, numberOfBooksPerDetailPage);
		modelMap.put("keyWord", keyWord);
		modelMap.put("maxBooks", this.browseBookService.getBooksAmount(keyWord));
		modelMap.put("books", books);
		modelMap.put("numberOfBooksPerDetailPage", numberOfBooksPerDetailPage);
		modelMap.put("pageNo", pageNo);
	}

	/**
	 * @return the numberOfBooksPerSummaryPage
	 */
	public int getNumberOfBooksPerSummaryPage() {
		return numberOfBooksPerSummaryPage;
	}

	/**
	 * @param numberOfBooksPerSummaryPage the numberOfBooksPerSummaryPage to set
	 */
	public void setNumberOfBooksPerSummaryPage(int numberOfBooksPerSummaryPage) {
		this.numberOfBooksPerSummaryPage = numberOfBooksPerSummaryPage;
	}

	/**
	 * @return the numberOfBooksPerDetailPage
	 */
	public int getNumberOfBooksPerDetailPage() {
		return numberOfBooksPerDetailPage;
	}

	/**
	 * @param numberOfBooksPerDetailPage the numberOfBooksPerDetailPage to set
	 */
	public void setNumberOfBooksPerDetailPage(int numberOfBooksPerDetailPage) {
		this.numberOfBooksPerDetailPage = numberOfBooksPerDetailPage;
	}

}
